home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / pvm34b3.zip / pvm34b3 / pvm3 / tracer / trcmess.c < prev    next >
C/C++ Source or Header  |  1997-07-22  |  16KB  |  954 lines

  1.  
  2. static char rcsid[] = 
  3.     "$Id: trcmess.c,v 4.2 1997/04/02 19:47:43 pvmsrc Exp $";
  4.  
  5. /*
  6.  *         Tracer version 1.0:  A Trace File Generator for PVM
  7.  *           Oak Ridge National Laboratory, Oak Ridge TN.
  8.  *           Authors:  James Arthur Kohl and G. A. Geist
  9.  *                   (C) 1994 All Rights Reserved
  10.  *
  11.  *                              NOTICE
  12.  *
  13.  * Permission to use, copy, modify, and distribute this software and
  14.  * its documentation for any purpose and without fee is hereby granted
  15.  * provided that the above copyright notice appear in all copies and
  16.  * that both the copyright notice and this permission notice appear
  17.  * in supporting documentation.
  18.  *
  19.  * Neither the Institution, Oak Ridge National Laboratory, nor the
  20.  * Authors make any representations about the suitability of this
  21.  * software for any purpose.  This software is provided ``as is''
  22.  * without express or implied warranty.
  23.  *
  24.  * Tracer was funded by the U.S. Department of Energy.
  25.  */
  26.  
  27.  
  28. /* Tracer Library Header */
  29.  
  30. #include "trclib.h"
  31.  
  32.  
  33. /* Routines */
  34.  
  35. int
  36. trc_recv_messages( ID, max_count, status )
  37. TRC_ID ID;
  38. int max_count;
  39. int *status;
  40. {
  41.     static int *tids = (int *) NULL;
  42.     static int ntids = 0;
  43.  
  44.     TRC_HOST H;
  45.  
  46.     TRC_ID DEAD_ID_last;
  47.     TRC_ID DEAD_ID_next;
  48.     TRC_ID DEAD_ID;
  49.  
  50.     int msgtag;
  51.     int others;
  52.     int ecnt;
  53.     int cnt;
  54.     int len;
  55.     int mid;
  56.     int num;
  57.     int tid;
  58.     int src;
  59.     int tmp;
  60.     int cc;
  61.     int i;
  62.  
  63.     /* Verify Message Codes Set */
  64.  
  65.     if ( TRC_HOST_ADD_NOTIFY_CODE == -1
  66.         || TRC_HOST_DEL_NOTIFY_CODE == -1
  67. #ifndef USE_PVM_33
  68.         || ID->event_ctx == -1 || ID->output_ctx == -1
  69. #endif
  70.         || ID->event_tag == -1 || ID->output_tag == -1 )
  71.     {
  72.         printf( "Error: Message Codes Not Set - %d %d %d %d %d %d\n",
  73.             TRC_HOST_ADD_NOTIFY_CODE, TRC_HOST_DEL_NOTIFY_CODE,
  74.             ID->event_ctx, ID->output_ctx,
  75.             ID->event_tag, ID->output_tag );
  76.         
  77.         return( -1 );
  78.     }
  79.  
  80.     /* Clear Out Flags */
  81.  
  82.     if ( status != NULL )
  83.         *status = TRC_MSG_STATUS_NONE;
  84.  
  85.     /* Init Event Counter */
  86.  
  87.     ecnt = 0;
  88.  
  89.     /* Check for Host Sync Updates */
  90.  
  91.     ecnt += trc_check_host_sync( ID );
  92.  
  93.     /* Receive Stuff */
  94.  
  95.     cnt = 0;
  96.  
  97.     while ( cnt < max_count
  98.         && (mid = trc_get_msg( ID, &len, &msgtag, &src, &others )) > 0 )
  99.     {
  100.         /* Set Activity Flag */
  101.  
  102.         if ( status != NULL )
  103.             *status |= TRC_MSG_STATUS_ACTIVE;
  104.  
  105.         /* Host Added */
  106.  
  107.         if ( msgtag == TRC_HOST_ADD_NOTIFY_CODE && src == 0x80000000 )
  108.         {
  109.             cc = pvm_upkint( &num, 1, 1 );
  110.  
  111.             if ( cc < 0 )
  112.                 pvm_perror( "Error Unpacking Host Add Notify" );
  113.  
  114.             else
  115.             {
  116.                 if ( num > ntids )
  117.                 {
  118.                     ntids = num * 2;
  119.  
  120.                     if ( tids )
  121.                         free( tids );
  122.  
  123.                     tids = (int *) malloc( (unsigned) ntids
  124.                         * sizeof(int) );
  125.                     trc_memcheck( tids, "Host Add Notify Tids Array" );
  126.                 }
  127.  
  128.                 cc = pvm_upkint( tids, num, 1 );
  129.  
  130.                 if ( cc < 0 )
  131.                     pvm_perror( "Error Unpacking Host Add TIDs" );
  132.  
  133.                 else
  134.                 {
  135.                     pvm_notify( PvmHostDelete, 100, num, tids );
  136.  
  137.                     ecnt += trc_handle_host_add_notify( ID, tids, num );
  138.                 }
  139.             }
  140.         }
  141.  
  142.         /* Host Deleted */
  143.  
  144.         else if ( msgtag == TRC_HOST_DEL_NOTIFY_CODE
  145.             && src == 0x80000000 )
  146.         {
  147.             cc = pvm_upkint( &tid, 1, 1 );
  148.  
  149.             if ( cc < 0 )
  150.                 pvm_perror( "Error Unpacking Host Delete Notify" );
  151.  
  152.             else
  153.                 ecnt += trc_handle_host_del_notify( ID, tid );
  154.         }
  155.  
  156.         /* PVM Trace Event */
  157.  
  158.         else if ( msgtag == ID->event_tag )
  159.         {
  160.             ecnt += trc_handle_trace_message( ID, src );
  161.  
  162.             if ( status != NULL )
  163.             {
  164.                 if ( ecnt )
  165.                     *status |= TRC_MSG_STATUS_OVERWRITE;
  166.  
  167.                 else
  168.                     *status |= TRC_MSG_STATUS_CLEANUP;
  169.             }
  170.         }
  171.  
  172.         /* PVM Output Event */
  173.  
  174.         else if ( msgtag == ID->output_tag )
  175.         {
  176.             ecnt += trc_handle_output_message( ID );
  177.  
  178.             if ( status != NULL )
  179.             {
  180.                 if ( ecnt )
  181.                     *status |= TRC_MSG_STATUS_OVERWRITE;
  182.  
  183.                 else
  184.                     *status |= TRC_MSG_STATUS_CLEANUP;
  185.             }
  186.         }
  187.  
  188.         /* Unknown Message */
  189.  
  190.         else
  191.         {
  192.             fprintf( stderr,
  193.                 "Tracer:  msg from 0x%x code %d len %d ?\n",
  194.                 src, msgtag, len );
  195.         }
  196.  
  197.         if ( pvm_freebuf( mid ) < 0 )
  198.             pvm_perror( "Error Freeing Message Buffer" );
  199.  
  200.         cnt++;
  201.     }
  202.  
  203.     if ( mid < 0 )
  204.     {
  205.         pvm_perror( "PVM System Failure" );
  206.  
  207.         printf( "Tracer exiting...\n" );
  208.  
  209.         return( -1 );
  210.     }
  211.  
  212.     if ( status != NULL )
  213.     {
  214.         if ( cnt == max_count )
  215.             *status |= TRC_MSG_STATUS_MORE;
  216.     }
  217.  
  218.     /* Try Flushing Dead IDs */
  219.  
  220.     if ( others )
  221.     {
  222.         DEAD_ID = TRC_DEAD_ID_LIST;
  223.  
  224.         DEAD_ID_last = (TRC_ID ) NULL;
  225.  
  226.         while ( DEAD_ID != NULL )
  227.         {
  228.             trc_recv_messages( DEAD_ID, 1, &tmp );
  229.  
  230.             if ( status != NULL )
  231.                 *status |= tmp;
  232.  
  233.             if ( trc_tevtasks_dead( DEAD_ID ) )
  234.             {
  235.                 DEAD_ID_next = DEAD_ID->next;
  236.  
  237.                 if ( DEAD_ID_last != NULL )
  238.                     DEAD_ID_last->next = DEAD_ID_next;
  239.  
  240.                 else
  241.                     TRC_DEAD_ID_LIST = DEAD_ID_next;
  242.  
  243.                 trc_free_tracer_id( &DEAD_ID );
  244.  
  245.                 DEAD_ID = DEAD_ID_next;
  246.             }
  247.  
  248.             else
  249.             {
  250.                 DEAD_ID_last = DEAD_ID;
  251.  
  252.                 DEAD_ID = DEAD_ID->next;
  253.             }
  254.         }
  255.     }
  256.  
  257.     return( ecnt );
  258. }
  259.  
  260.  
  261. int
  262. trc_get_msg( ID, len, msgtag, src, others )
  263. TRC_ID ID;
  264. int *len;
  265. int *msgtag;
  266. int *src;
  267. int *others;
  268. {
  269.     int mid;
  270.     int tag;
  271.  
  272.     /* Reset "Others" Flag */
  273.  
  274.     if ( others != NULL )
  275.         *others = TRC_FALSE;
  276.  
  277.     /* Check for Host Add */
  278.  
  279.     if ( (mid = pvm_nrecv( -1, TRC_HOST_ADD_NOTIFY_CODE )) > 0 )
  280.     {
  281.         if ( pvm_bufinfo( mid, len, msgtag, src ) < 0 )
  282.         {
  283.             pvm_perror( "Error Checking Message Buffer" );
  284.         
  285.             return( -1 );
  286.         }
  287.  
  288.         return( mid );
  289.     }
  290.  
  291.     else if ( mid < 0 )
  292.     {
  293.         pvm_perror( "Error Checking Host Add Notify Message" );
  294.             
  295.         return( -1 );
  296.     }
  297.  
  298.     /* Check for Host Delete */
  299.  
  300.     if ( (mid = pvm_nrecv( -1, TRC_HOST_DEL_NOTIFY_CODE )) > 0 )
  301.     {
  302.         if ( pvm_bufinfo( mid, len, msgtag, src ) < 0 )
  303.         {
  304.             pvm_perror( "Error Checking Message Buffer" );
  305.         
  306.             return( -1 );
  307.         }
  308.  
  309.         return( mid );
  310.     }
  311.  
  312.     else if ( mid < 0 )
  313.     {
  314.         pvm_perror( "Error Checking Host Delete Notify Message" );
  315.             
  316.         return( -1 );
  317.     }
  318.  
  319.     /* Any message at all? */
  320.  
  321.     if ( (mid = pvm_probe( -1, -1 )) > 0 )
  322.     {
  323.         if ( pvm_bufinfo( mid, len, &tag, src ) < 0 )
  324.         {
  325.             pvm_perror( "Error Checking Message Buffer" );
  326.         
  327.             return( -1 );
  328.         }
  329.  
  330.         if ( msgtag != NULL )
  331.             *msgtag = tag;
  332.  
  333.         /* The next one's for us... */
  334.  
  335.         if ( tag == ID->event_tag || tag == ID->output_tag )
  336.         {
  337.             pvm_setrbuf( mid );
  338.  
  339.             return( mid );
  340.         }
  341.  
  342.         /* Or not... */
  343.  
  344.         else
  345.         {
  346.             if ( others != NULL )
  347.                 *others = TRC_TRUE;
  348.  
  349.             return( 0 );
  350.         }
  351.     }
  352.  
  353.     /* System Error */
  354.  
  355.     else if ( mid < 0 )
  356.     {
  357.         pvm_perror( "Error Probing for Trace / Output Messages" );
  358.         
  359.         return( -1 );
  360.     }
  361.  
  362.     /* No Messages */
  363.  
  364.     else
  365.         return( 0 );
  366. }
  367.  
  368.  
  369. int
  370. trc_handle_trace_message( ID, src )
  371. TRC_ID ID;
  372. int src;
  373. {
  374.     TRC_DATADESC DD;
  375.  
  376.     TRC_TEVDESC TD;
  377.  
  378.     TRC_TEVTASK TT;
  379.  
  380.     TRC_HOST H;
  381.  
  382.     TRC_DID dptr;
  383.  
  384.     char diddesc[1024];
  385.     char tmp[1024];
  386.     char did[8];
  387.  
  388.     int desc_done;
  389.     int did_done;
  390.     int done;
  391.     int omit;
  392.  
  393.     int entry_exit;
  394.     int dump_event;
  395.     int pvmd_tid;
  396.     int did_int;
  397.     int tusec;
  398.     int tsec;
  399.     int ecnt;
  400.     int eid;
  401.     int tid;
  402.     int dt;
  403.  
  404.     int marker;
  405.     int nest;
  406.  
  407.     ecnt = 0;
  408.  
  409.     TRC_PVMCKERR( pvm_upkint( &marker, 1, 1 ),
  410.         "Unpacking Trace Message", return( ecnt ) );
  411.  
  412.     /* Old PVM 3.3 Trace Format */
  413.  
  414.     if ( marker > 0 )
  415.     {
  416.         tsec = marker;
  417.  
  418.         TRC_PVMCKERR( pvm_upkint( &tusec, 1, 1 ),
  419.             "Event Parse Error", return( ecnt ) );
  420.  
  421.         TRC_PVMCKERR( pvm_upkint( &tid, 1, 1 ),
  422.             "Event Parse Error", return( ecnt ) );
  423.  
  424.         TRC_PVMCKERR( pvm_upkint( &eid, 1, 1 ),
  425.             "Event Parse Error", return( ecnt ) );
  426.  
  427.         ecnt += trc_store_old_trace_event( ID, tsec, tusec, tid, eid );
  428.  
  429.         return( ecnt );
  430.     }
  431.  
  432.     /* New PVM 3.4 Format */
  433.  
  434.     /* Get Task & Host Info */
  435.  
  436.     TT = trc_get_tevtask_tid( ID, src );
  437.  
  438.     pvmd_tid = pvm_tidtohost( src );
  439.  
  440.     if ( !pvmd_tid )
  441.         pvmd_tid = pvm_tidtohost( TRC_TID );
  442.  
  443.     H = trc_get_host_tid( pvmd_tid );
  444.  
  445.     /* Set Leftover Event Omit Flag */
  446.  
  447.     omit = ( ID->trace_out == NULL
  448.         || ( TT != NULL && TRC_TASK_OMIT( TT ) ) )
  449.             ? TRC_TRUE : TRC_FALSE;
  450.  
  451.     /* Process Event Message */
  452.  
  453.     nest = 0;
  454.  
  455.     done = 0;
  456.  
  457.     do
  458.     {
  459.         switch ( marker )
  460.         {
  461.             case TEV_MARK_EVENT_BUFFER:
  462.             {
  463.                 nest++;
  464.  
  465.                 break;
  466.             }
  467.  
  468.             case TEV_MARK_EVENT_BUFFER_END:
  469.             {
  470.                 if ( !(--nest) )
  471.                     done++;
  472.  
  473.                 break;
  474.             }
  475.  
  476.             case TEV_MARK_DATA_ID:
  477.             {
  478.                 did_done = 0;
  479.  
  480.                 do
  481.                 {
  482.                     TRC_PVMCKERR( pvm_upkint( &did_int, 1, 1 ),
  483.                         "Data ID Message", return( ecnt ) );
  484.  
  485.                     if ( did_int != TEV_MARK_DATA_ID_END )
  486.                     {
  487.                         TRC_PVMCKERR( pvm_upkstr( did ),
  488.                             "Data ID Name", return( ecnt ) );
  489.  
  490.                         TRC_PVMCKERR( pvm_upkstr( diddesc ),
  491.                             "Data ID Description", return( ecnt ) );
  492.  
  493.                         dptr = (TRC_DID) trc_lookup_trie( TRC_DID_TRIE,
  494.                             did );
  495.                         
  496.                         if ( dptr == NULL
  497.                             || dptr->id != did_int
  498.                             || strcmp( dptr->desc, diddesc ) )
  499.                         {
  500.                             dptr = trc_create_did();
  501.  
  502.                             dptr->id = did_int;
  503.  
  504.                             dptr->name = trc_copy_str( did );
  505.  
  506.                             dptr->desc = trc_copy_str( diddesc );
  507.  
  508.                             dptr->next = TRC_DID_LIST;
  509.  
  510.                             TRC_DID_LIST = dptr;
  511.  
  512.                             trc_add_to_trie( TRC_DID_TRIE,
  513.                                 dptr->name, (void *) dptr );
  514.                         }
  515.  
  516.                         trc_set_didlist( H, dptr );
  517.                     }
  518.  
  519.                     else
  520.                         did_done++;
  521.                 }
  522.                 while ( !did_done );
  523.  
  524.                 if ( !nest )
  525.                     done++;
  526.  
  527.                 break;
  528.             }
  529.  
  530.             case TEV_MARK_EVENT_DESC:
  531.             {
  532.                 TD = trc_create_tevdesc();
  533.  
  534.                 TD->refcount = 1;
  535.  
  536.                 TRC_PVMCKERR( pvm_upkint( &eid, 1, 1 ),
  537.                     "Event Descriptor ID", return( ecnt ) );
  538.  
  539.                 TD->eid = eid & ~( TEV_EVENT_ENTRY | TEV_EVENT_EXIT );
  540.  
  541.                 if ( eid & TEV_EVENT_ENTRY )
  542.                     TD->entry_exit = TRC_ENTRY_TEV;
  543.  
  544.                 else if ( eid & TEV_EVENT_EXIT )
  545.                     TD->entry_exit = TRC_EXIT_TEV;
  546.  
  547.                 else
  548.                     TD->entry_exit = TRC_IGNORE_TEV;
  549.  
  550.                 TRC_PVMCKERR( pvm_upkstr( tmp ),
  551.                     "Event Descriptor Name", return( ecnt ) );
  552.  
  553.                 TD->name = trc_copy_str( tmp );
  554.         
  555.                 desc_done = 0;
  556.  
  557.                 do
  558.                 {
  559.                     TRC_PVMCKERR( pvm_upkint( &did_int, 1, 1 ),
  560.                         "Semantic Data ID", return( ecnt ) );
  561.  
  562.                     if ( did_int != TEV_MARK_EVENT_DESC_END )
  563.                     {
  564.                         if ( TD->ddesc == NULL )
  565.                             DD = TD->ddesc = trc_create_datadesc();
  566.  
  567.                         else
  568.                             DD = DD->next = trc_create_datadesc();
  569.  
  570.                         if ( H->didlist == NULL )
  571.                         {
  572.                             printf(
  573.                             "Warning: Missing DID List For Host %s\n",
  574.                                 H->name );
  575.                         }
  576.  
  577.                         DD->did = trc_get_did( H, did_int );
  578.  
  579.                         if ( DD->did == NULL )
  580.                         {
  581.                             printf( "Error: DID=%d Not Found\n",
  582.                                 did_int );
  583.  
  584.                             trc_free_tevdesc( &TD );
  585.  
  586.                             return( ecnt );
  587.                         }
  588.  
  589.                         TRC_PVMCKERR( pvm_upkint( &dt, 1, 1 ),
  590.                             "Data Type", return( ecnt ) );
  591.  
  592.                         DD->dt = dt &
  593.                             ~( TEV_DATA_SCALAR | TEV_DATA_ARRAY );
  594.  
  595.                         DD->array = dt &
  596.                             ( TEV_DATA_SCALAR | TEV_DATA_ARRAY );
  597.  
  598.                         if ( !trc_unpack_data_value( DD ) )
  599.                         {
  600.                             trc_free_tevdesc( &TD );
  601.  
  602.                             return( ecnt );
  603.                         }
  604.                     }
  605.  
  606.                     else
  607.                         desc_done++;
  608.                 }
  609.                 while ( !desc_done );
  610.  
  611.                 dump_event = trc_add_tevdesc( ID, &TD, src, omit );
  612.  
  613.                 trc_set_tevlist( TT, H, TD );
  614.  
  615.                 if ( TD->dump )
  616.                     trc_dump_tevdesc( ID, TD, src );
  617.  
  618.                 if ( dump_event )
  619.                     trc_store_data_values( ID, TD, src, omit );
  620.  
  621.                 if ( !omit )
  622.                     ecnt++;
  623.  
  624.                 if ( !nest )
  625.                     done++;
  626.  
  627.                 break;
  628.             }
  629.  
  630.             case TEV_MARK_USER_EVENT_RECORD:
  631.             {
  632.                 TD = trc_create_tevdesc();
  633.  
  634.                 TD->refcount = 1;
  635.  
  636.                 TRC_PVMCKERR( pvm_upkint( &eid, 1, 1 ),
  637.                     "Event Descriptor ID", return( ecnt ) );
  638.  
  639.                 TD->eid = eid & ~( TEV_EVENT_ENTRY | TEV_EVENT_EXIT );
  640.  
  641.                 if ( eid & TEV_EVENT_ENTRY )
  642.                     TD->entry_exit = TRC_ENTRY_TEV;
  643.  
  644.                 else if ( eid & TEV_EVENT_EXIT )
  645.                     TD->entry_exit = TRC_EXIT_TEV;
  646.  
  647.                 else
  648.                     TD->entry_exit = TRC_IGNORE_TEV;
  649.  
  650.                 TRC_PVMCKERR( pvm_upkstr( tmp ),
  651.                     "Event Descriptor Name", return( ecnt ) );
  652.  
  653.                 TD->name = trc_copy_str( tmp );
  654.         
  655.                 /* Yank Out Hardwired Timestamp */
  656.  
  657.                 DD = TD->ddesc = trc_create_datadesc();
  658.  
  659.                 DD->did = trc_get_did( (TRC_HOST) NULL, TEV_DID_TS );
  660.  
  661.                 DD->dt = TEV_DATA_INT;
  662.                 DD->array = TEV_DATA_SCALAR;
  663.  
  664.                 if ( !trc_unpack_data_value( DD ) )
  665.                 {
  666.                     trc_free_tevdesc( &TD );
  667.  
  668.                     return( ecnt );
  669.                 }
  670.  
  671.                 DD = DD->next = trc_create_datadesc();
  672.  
  673.                 DD->did = trc_get_did( (TRC_HOST) NULL, TEV_DID_TU );
  674.  
  675.                 DD->dt = TEV_DATA_INT;
  676.                 DD->array = TEV_DATA_SCALAR;
  677.  
  678.                 if ( !trc_unpack_data_value( DD ) )
  679.                 {
  680.                     trc_free_tevdesc( &TD );
  681.  
  682.                     return( ecnt );
  683.                 }
  684.  
  685.                 desc_done = 0;
  686.  
  687.                 do
  688.                 {
  689.                     TRC_PVMCKERR( pvm_upkint( &dt, 1, 1 ),
  690.                         "Data Type", return( ecnt ) );
  691.  
  692.                     if ( dt != TEV_MARK_USER_EVENT_RECORD_END )
  693.                     {
  694.                         DD = DD->next = trc_create_datadesc();
  695.  
  696.                         DD->dt = dt &
  697.                             ~( TEV_DATA_SCALAR | TEV_DATA_ARRAY );
  698.  
  699.                         DD->array = dt &
  700.                             ( TEV_DATA_SCALAR | TEV_DATA_ARRAY );
  701.  
  702.                         if ( !trc_unpack_data_value( DD ) )
  703.                         {
  704.                             trc_free_tevdesc( &TD );
  705.  
  706.                             return( ecnt );
  707.                         }
  708.                     }
  709.  
  710.                     else
  711.                         desc_done++;
  712.                 }
  713.                 while ( !desc_done );
  714.  
  715.                 dump_event = trc_add_tevdesc( ID, &TD, src, omit );
  716.  
  717.                 if ( TD->dump )
  718.                     trc_dump_tevdesc( ID, TD, src );
  719.  
  720.                 if ( dump_event )
  721.                     trc_store_data_values( ID, TD, src, omit );
  722.  
  723.                 if ( !omit )
  724.                     ecnt++;
  725.  
  726.                 if ( !nest )
  727.                     done++;
  728.  
  729.                 break;
  730.             }
  731.  
  732.             case TEV_MARK_EVENT_RECORD:
  733.             {
  734.                 TRC_PVMCKERR( pvm_upkint( &eid, 1, 1 ),
  735.                     "Event ID", return( ecnt ) );
  736.  
  737.                 if ( eid & TEV_EVENT_ENTRY )
  738.                     entry_exit = TRC_ENTRY_TEV;
  739.  
  740.                 else if ( eid & TEV_EVENT_EXIT )
  741.                     entry_exit = TRC_EXIT_TEV;
  742.  
  743.                 else
  744.                     entry_exit = TRC_IGNORE_TEV;
  745.  
  746.                 eid &= ~( TEV_EVENT_ENTRY | TEV_EVENT_EXIT );
  747.  
  748.                 TD = trc_get_tevdesc( TT, H, eid, entry_exit );
  749.  
  750.                 if ( TD != NULL )
  751.                 {
  752.                     if ( trc_store_trace_event( ID, TD, src, omit ) )
  753.                         ecnt++;
  754.                 }
  755.  
  756.                 else
  757.                     printf( "Error: Descriptor Not Found\n\n" );
  758.  
  759.                 if ( !nest )
  760.                     done++;
  761.  
  762.                 break;
  763.             }
  764.         }
  765.  
  766.         if ( !done )
  767.         {
  768.             TRC_PVMCKERR( pvm_upkint( &marker, 1, 1 ),
  769.                 "Unpacking Trace Message", return( ecnt ) );
  770.         }
  771.     }
  772.     while ( !done );
  773.  
  774.     return( ecnt );
  775. }
  776.  
  777.  
  778. int
  779. trc_handle_output_message( ID )
  780. TRC_ID ID;
  781. {
  782.     TRC_TEVTASK TT;
  783.  
  784.     char tmp[255];
  785.     char msg[255];
  786.  
  787.     char *output;
  788.  
  789.     int ecnt;
  790.     int omit;
  791.     int len;
  792.     int tid;
  793.  
  794.     ecnt = 0;
  795.  
  796.     TRC_PVMCKERR( pvm_upkint( &tid, 1, 1 ),
  797.         "Error Unpacking Output Message", return( ecnt ) );
  798.     
  799.     TRC_PVMCKERR( pvm_upkint( &len, 1, 1 ),
  800.         "Error Unpacking Output Length", return( ecnt ) );
  801.  
  802.     /* Set Leftover Event Omit Flag */
  803.  
  804.     TT = trc_get_tevtask_tid( ID, tid );
  805.  
  806.     omit = ( ID->trace_out == NULL
  807.         || ( TT != NULL && TRC_TASK_OMIT( TT ) ) )
  808.             ? TRC_TRUE : TRC_FALSE;
  809.  
  810.     /* Unpack Output */
  811.  
  812.     if ( len > 0 )
  813.     {
  814.         output = (char *) malloc( (unsigned) ( len + 1 )
  815.             * sizeof(char) );
  816.         trc_memcheck( output, "PVM Output String" );
  817.  
  818.         TRC_PVMCKERR( pvm_upkbyte( output, len, 1 ),
  819.             "Error Unpacking Task Output",
  820.             free(output); return( ecnt ) );
  821.  
  822.         output[ len ] = '\0';
  823.  
  824.         if ( !omit )
  825.             ecnt = trc_store_output_event( ID, tid, output, len );
  826.  
  827.         free( output );
  828.     }
  829.  
  830.     else
  831.     {
  832.         switch ( len )
  833.         {
  834.             case 0:
  835.             {
  836.                 if ( !omit )
  837.                 {
  838.                     sprintf( tmp, "GOTEOF\n" );
  839.  
  840.                     ecnt = trc_store_output_event( ID,
  841.                         tid, tmp, strlen(tmp) );
  842.                 }
  843.  
  844.                 if ( TT != NULL )
  845.                 {
  846.                     if ( TT->tevstatus == TRC_TASK_ALIVE )
  847.                     {
  848.                         TT->outstatus = TRC_TASK_EOF;
  849.  
  850.                         trc_check_for_dead_host( ID, TT );
  851.  
  852.                         if ( !trc_tevtasks_alive( ID ) )
  853.                             trc_end_trace( ID );
  854.                     }
  855.  
  856.                     else
  857.                         TT->outstatus = TRC_TASK_EOF;
  858.                 }
  859.  
  860.                 else if ( !omit )
  861.                 {
  862.                     printf(
  863.                         "\nWarning: GOTEOF Unknown Task TID=0x%x.\n\n",
  864.                         tid );
  865.                 }
  866.  
  867.                 break;
  868.             }
  869.  
  870.             case -1:
  871.             {
  872.                 if ( omit )
  873.                     break;
  874.  
  875.                 sprintf( tmp, "GOTSPAWN\n" );
  876.  
  877.                 ecnt = trc_store_output_event( ID,
  878.                     tid, tmp, strlen(tmp) );
  879.  
  880.                 if ( TT == NULL )
  881.                 {
  882.                     sprintf( msg, "Task TID=0x%x Connected to %s",
  883.                         tid, TRC_NAME );
  884.  
  885.                     trc_status_msg( ID, msg );
  886.  
  887.                     TT = trc_create_tevtask();
  888.  
  889.                     TT->tid = tid;
  890.  
  891.                     TT->outstatus = TRC_TASK_OUT;
  892.                     TT->tevstatus = TRC_TASK_NOLIFE;
  893.  
  894.                     TT->next = ID->tevtask_list;
  895.  
  896.                     ID->tevtask_list = TT;
  897.                 }
  898.  
  899.                 else
  900.                     TT->outstatus = TRC_TASK_OUT;
  901.  
  902.                 break;
  903.             }
  904.  
  905.             case -2:
  906.             {
  907.                 if ( omit )
  908.                     break;
  909.  
  910.                 sprintf( tmp, "CREATION\n" );
  911.  
  912.                 ecnt = trc_store_output_event( ID,
  913.                     tid, tmp, strlen(tmp) );
  914.  
  915.                 if ( TT == NULL )
  916.                 {
  917.                     sprintf( msg, "Task TID=0x%x Connected to %s",
  918.                         tid, TRC_NAME );
  919.  
  920.                     trc_status_msg( ID, msg );
  921.  
  922.                     TT = trc_create_tevtask();
  923.  
  924.                     TT->tid = tid;
  925.  
  926.                     TT->outstatus = TRC_TASK_OUT;
  927.                     TT->tevstatus = TRC_TASK_NOLIFE;
  928.  
  929.                     TT->next = ID->tevtask_list;
  930.  
  931.                     ID->tevtask_list = TT;
  932.                 }
  933.  
  934.                 else
  935.                     TT->outstatus = TRC_TASK_OUT;
  936.  
  937.                 break;
  938.             }
  939.  
  940.             default:
  941.             {
  942.                 if ( !omit )
  943.                 {
  944.                     fprintf( stderr,
  945.                         "Console: unknown output msg 0x%x?\n", tid );
  946.                 }
  947.             }
  948.         }
  949.     }
  950.  
  951.     return( ecnt );
  952. }
  953.  
  954.